/*
 * Copyright (c) 2008, Roman Bosak All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer. - Redistributions in
 * binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other
 * materials provided with the distribution. - Neither the name of the
 * DailyDevelopment nor the names of its contributors may be used to endorse or
 * promote products derived from this software without specific prior written
 * permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package com.atlassian.jira.web.action;

import java.lang.reflect.Field;
import java.util.HashMap;

import org.easymock.EasyMock;
import org.junit.Before;
import org.picocontainer.PicoContainer;

import webwork.action.ActionContext;

import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.portal.PortalManager;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.security.PermissionManager;
import com.atlassian.jira.util.EmailFormatter;
import com.atlassian.jira.util.GroupPermissionChecker;
import com.atlassian.seraph.auth.DefaultAuthenticator;
import com.dailydev.jira.portal.IDashboardSharingPortalManager;
import com.dailydev.jira.portal.config.IPortalPageSharingConfiguration;
import com.opensymphony.user.ProviderAccessor;
import com.opensymphony.user.User;
import com.opensymphony.user.provider.AccessProvider;
import com.opensymphony.user.provider.CredentialsProvider;

/**
 * This class provide default setup of Jira testing environment with registered
 * mocks and logged user. This class is intended to be extended by concrete test
 * cases.
 * 
 * @author Roman Bosak, roman.bosak@gmail.com
 */
public abstract class JiraTestCase {

    protected static final String USER_FREUD = "freud";
    protected static final String USER_JUNG = "jung";
    protected PicoContainer container;
    protected CustomFieldManager customFieldManager;
    protected IssueManager issueManager;
    protected HashMap<String, Object> session;
    protected IPortalPageSharingConfiguration configuration;
    protected IDashboardSharingPortalManager portalManager;
    protected JiraAuthenticationContext jiraAuthenticationContext;
    protected PermissionManager permissionManager;
    protected GroupPermissionChecker groupPermissionChecker;
    protected EmailFormatter emailFormatter;

    public JiraTestCase() {
        super();
    }

    /**
     * Sets up the environment for testing execution. Configuring PicoContainer
     * mock to behave as standard PicoContainer implementation and registering
     * components required by concrete tests. Also creates one {@link User}
     * instance and registers it as logged in user.
     * 
     * @throws Exception
     */
    @Before
    public void setUp() throws Exception {
        container = EasyMock.createNiceMock(PicoContainer.class);

        // creates and registers CustomFieldManager mock
        customFieldManager = EasyMock.createNiceMock(CustomFieldManager.class);
        EasyMock.expect(
                container.getComponentInstanceOfType(CustomFieldManager.class))
                .andStubReturn(customFieldManager);

        // creates and registers IssueManager mock
        issueManager = EasyMock.createNiceMock(IssueManager.class);
        EasyMock.expect(
                container.getComponentInstanceOfType(IssueManager.class))
                .andStubReturn(issueManager);

        // creates and registers IDashboardSharingConfiguration mock
        configuration = EasyMock
                .createMock(IPortalPageSharingConfiguration.class);
        EasyMock
                .expect(
                        container
                                .getComponentInstanceOfType(IPortalPageSharingConfiguration.class))
                .andStubReturn(configuration);

        // creates and registers PortalManager mock
        portalManager = EasyMock
                .createNiceMock(IDashboardSharingPortalManager.class);
        EasyMock.expect(
                container.getComponentInstanceOfType(PortalManager.class))
                .andStubReturn(portalManager);

        // creates and registers JiraAuthenticationContext mock
        jiraAuthenticationContext = EasyMock
                .createMock(JiraAuthenticationContext.class);
        EasyMock
                .expect(
                        container
                                .getComponentInstance(JiraAuthenticationContext.class))
                .andStubReturn(jiraAuthenticationContext);

        // creates and registers PermissionManager mock
        permissionManager = EasyMock.createMock(PermissionManager.class);
        EasyMock
                .expect(container.getComponentInstance(PermissionManager.class))
                .andStubReturn(permissionManager);

        // creates and registers GroupPermissionChecker mock
        groupPermissionChecker = EasyMock
                .createMock(GroupPermissionChecker.class);
        EasyMock
                .expect(
                        container
                                .getComponentInstanceOfType(GroupPermissionChecker.class))
                .andStubReturn(groupPermissionChecker);

        // creates and registers EmailFormatter mock
        emailFormatter = EasyMock.createMock(EmailFormatter.class);
        EasyMock.expect(
                container.getComponentInstanceOfType(EmailFormatter.class))
                .andStubReturn(emailFormatter);

        EasyMock.replay(container);

        // set ComponentManager to refer to mock implementation of PicoContainer
        // - 'container' reference
        ComponentManager componentManager = ComponentManager.getInstance();
        Field containerField = ComponentManager.class
                .getDeclaredField("container");
        containerField.setAccessible(true);
        containerField.set(componentManager, container);

        // create session
        session = new HashMap<String, Object>();
        ActionContext.setSession(session);

        // sets logged user
        User user = createUser(USER_JUNG);
        setLoggedInUser(user);
    }

    /**
     * @param user
     * @return
     */
    protected Object setLoggedInUser(User user) { // NOPMD by bosakrom on
        // 23.4.08 18:15
        return session.put(DefaultAuthenticator.LOGGED_IN_KEY, user);
    }

    /**
     * @return
     */
    protected User createUser(String name) { // NOPMD by bosakrom on 23.4.08
        // 18:15
        ProviderAccessor providerAccessor = EasyMock
                .createNiceMock(ProviderAccessor.class);
        CredentialsProvider credentialsProvider = EasyMock
                .createMock(CredentialsProvider.class);
        EasyMock.expect(providerAccessor.getCredentialsProvider(name))
                .andReturn(credentialsProvider);
        EasyMock.expect(
                credentialsProvider.load(EasyMock.eq(name), EasyMock
                        .isA(User.Accessor.class))).andReturn(true);
        AccessProvider accessProvider = EasyMock
                .createMock(AccessProvider.class);
        EasyMock.expect(
                providerAccessor.getAccessProvider(EasyMock.isA(String.class)))
                .andStubReturn(accessProvider);
        EasyMock.replay(providerAccessor, credentialsProvider);

        User user = new User(name, providerAccessor);

        return user;
    }

}